﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TestesFixacao.Dominio.Modelos;
using TestesFixacao.WindowsApp.Refatorado.Controls.Shared;

namespace TestesFixacao.WindowsApp.Refatorado.Controls.QuestaoForms
{
    public partial class QuestaoDialog : BaseDialog
    {
        private Questao _questao;
        private List<Alternativa> _lstAlternativas = new List<Alternativa>();

        public QuestaoDialog(List<Materia> materias, string descricao)
        {
            InitializeComponent();

            if (materias == null)
                throw new ArgumentNullException("materias", "Materias não pode ser nulo.");

            if (materias.Count == 0)
                throw new ArgumentOutOfRangeException("materias", "0", "Deverá ter no mínimo uma materias.");

            if (string.IsNullOrEmpty(descricao))
                throw new ArgumentNullException("descricao");

            base.DescricaoTela = descricao;

            base.RedimensionaJanela(new Size(Size.Width, Size.Height));

            base.RegistraControles(txtNumero, txtEnunciado, txtResposta, cmbAlternativa, cmbMateria, chkCorreta);

            cmbMateria.Items.OverrideAll(materias);
            _lstAlternativas.AddRange(new[]
                                       {
                                           new Alternativa { Letra = 'A' },
                                           new Alternativa { Letra = 'B' },
                                           new Alternativa { Letra = 'C' },
                                           new Alternativa { Letra = 'D' }
                                       });
            AtualizaAlternativasComponentes();
        }

        public Questao Questao
        {
            get { return _questao; }
            set
            {
                _configurando = true;
                _questao = value;

                txtNumero.Text = _questao.Numero.ToString();
                txtEnunciado.Text = _questao.Enunciado;
                cmbMateria.SelectedItem = _questao.Materia;

                txtEnunciado.Select();

                if (_questao.Alternativas.Count > 0)
                {
                    _lstAlternativas.Clear();
                    _lstAlternativas.AddRange(_questao.Alternativas);

                    AtualizaAlternativasComponentes();
                }

                _configurando = false;

                DoOperation();
            }
        }

        protected override void DoOperation()
        {
            if (_configurando)
                return;

            _questao.Numero = int.Parse(txtNumero.Text);
            _questao.Enunciado = txtEnunciado.Text;
            _questao.Materia = cmbMateria.SelectedItem as Materia;

            _questao.Alternativas.Clear();

            try
            {
                _lstAlternativas.ForEach(x => _questao.AdicionaAlternativa(x));

                _questao.Valida();

                Main.Instance.ShowMessageInFooter("A alternativa já pode ser gravada");

                HabilitaBotaoOk();
            }
            catch (Exception ex)
            {
                DesabilitaBotaoOk();
                Main.Instance.ShowMessageInFooter(ex.Message);
            }
        }

        private void AtualizaAlternativasComponentes()
        {
            cmbAlternativa.Items.OverrideAll(_lstAlternativas);

            lsbAlternativas.Items.OverrideAll(_lstAlternativas);
        }

        private void btnAdicionar_Click(object sender, EventArgs e)
        {
            var letra = _lstAlternativas.Last().Letra.Next();

            _lstAlternativas.Add(new Alternativa { Letra = letra });

            DoOperation();

            AtualizaAlternativasComponentes();
        }

        /// <summary>
        /// evento utilizado pelo combobox e também pelo listbox das alternativas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SelectedIndexChanged(object sender, EventArgs e)
        {
            Alternativa alternativa = null;

            if (sender is ComboBox)
                alternativa = ((ComboBox)sender).SelectedItem as Alternativa;
            else
                alternativa = ((ListBox)sender).SelectedItem as Alternativa;

            lsbAlternativas.SelectedItem = alternativa;
            cmbAlternativa.SelectedItem = alternativa;
            chkCorreta.Checked = alternativa.Correta;

            txtResposta.Text = alternativa.Resposta;
        }

        /// <summary>
        /// evento lançado pelo componente de resposta da alternativa
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtResposta_TextChanged(object sender, EventArgs e)
        {
            var a = cmbAlternativa.SelectedItem as Alternativa;

            a.Resposta = txtResposta.Text;

            AtualizaAlternativasComponentes();

            cmbAlternativa.SelectedItem = a;

            DoOperation();
        }

        private void cbCorreta_CheckedChanged(object sender, EventArgs e)
        {
            var a = cmbAlternativa.SelectedItem as Alternativa;
            a.Correta = chkCorreta.Checked;

            DoOperation();
        }

        private void lsbAlternativas_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Back)
            {
                Alternativa alternativa = lsbAlternativas.SelectedItem as Alternativa;
                _lstAlternativas.Remove(alternativa);
            }
        }
    }

    /// <summary>
    /// Extension Method da classe char
    /// </summary>
    public static class CharExtension
    {
        /// <summary>
        /// reponsável por trazer a próxima letra da alternativa
        /// </summary>
        /// <param name="instancia"></param>
        /// <returns></returns>
        public static char Next(this char instancia)
        {
            int numero = instancia;

            numero++;

            return (char)numero;
        }
    }
}